#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string>
#include <string.h>
#include <map>
#include <json/json.h>
#include <iostream>
#include <fstream>
#include <sys/types.h>
#include "mylog.h"
#include "MyException.h"
#include "config.h"

using namespace std;

const char* const Config::m_StrLogLevel = "LogLevel";
const char* const Config::m_StrLogSize  = "LogSize";
const char* const Config::m_StrLogName  = "LogName";

const char* const Config::m_StrQuerySendTimeOut = "SendTimeOut_MS";
const char* const Config::m_StrQueryRecvTimeOut = "RecvTimeOut_MS";
const char* const Config::m_StrCiPort   = "CiPort";
const char* const Config::m_StrServiceThreadNum = "ServiceThreadNum";
const char* const Config::m_StrThreadBufferSize = "ThreadBufferSize";
const char* const Config::m_StrEpollSize = "EpollSize";

Config::Config(const char* configpath)
{
    // DEFAULT CONFIG
    m_log_level = mylog :: ROUTN;
    m_log_size  = 1 << 30;
    m_log_name  = PROJNAME;
    SETLOG(m_log_level, m_log_size, m_log_name);

    m_pollsize           = 128;
    m_wtimeout_ms        = 1000;
    m_rtimeout_ms        = 1000;
    m_ci_port            = 1983;
    m_service_thread_num = 20;
    m_thread_buffer_size = 10*1024*1024;

    // CUSTOMIZE CONFIG
    Json::Value root;
    Json::Reader reader;
    ifstream in(configpath);
    if (! reader.parse(in, root))
    {
        FATAL("json format error. USING DEFAULT CONFIG.");
        MyThrowAssert(0);
    }

    Json::Value logConfig = root["LOG"];
    if (! logConfig.isNull()) {
        m_log_level = logConfig[m_StrLogLevel].isNull() ? m_log_level : logConfig[m_StrLogLevel].asInt();
        m_log_size  = logConfig[m_StrLogSize].isNull()  ? m_log_size  : logConfig[m_StrLogSize].asInt();
        m_log_name  = logConfig[m_StrLogName].isNull()  ? m_log_name  : logConfig[m_StrLogName].asCString();
        SETLOG(m_log_level, m_log_size, m_log_name);
    }

    Json::Value qSrvConfig = root["CI_SERVER"];
    if (! qSrvConfig.isNull()) {
        m_pollsize    = qSrvConfig[m_StrEpollSize].isNull() ? m_pollsize : qSrvConfig[m_StrEpollSize].asInt();
        m_wtimeout_ms = qSrvConfig[m_StrQuerySendTimeOut].isNull() ? m_wtimeout_ms : qSrvConfig[m_StrQuerySendTimeOut].asInt();
        m_rtimeout_ms = qSrvConfig[m_StrQueryRecvTimeOut].isNull() ? m_rtimeout_ms : qSrvConfig[m_StrQueryRecvTimeOut].asInt();
        m_ci_port  = qSrvConfig[m_StrCiPort].isNull() ? m_ci_port : qSrvConfig[m_StrCiPort].asInt();
        m_service_thread_num = qSrvConfig[m_StrServiceThreadNum].isNull() ?
            m_service_thread_num : qSrvConfig[m_StrServiceThreadNum].asInt();
        m_thread_buffer_size = qSrvConfig[m_StrThreadBufferSize].isNull() ?
            m_thread_buffer_size : qSrvConfig[m_StrThreadBufferSize].asInt();
    }

    Json::Value qQueueConfig = root["QUEUE"];
    if (! qQueueConfig.isNull()) {
        for (uint32_t i=0; i<qQueueConfig.size(); i++)
        {
            if (m_queue_map.end() != m_queue_map.find(string(qQueueConfig[i].asCString())))
            {                   
                FATAL("dup queue_name[%s]", qQueueConfig[i].asCString());
                MyThrowAssert(0);
            }

            FileLinkBlock * pflb = new FileLinkBlock(qQueueConfig[i].asCString(), qQueueConfig[i].asCString(), false);
            m_queue_map[string(qQueueConfig[i].asCString())] = pflb;
            ROUTN("queue[%s] init.", qQueueConfig[i].asCString());
        }
    }
    MyThrowAssert(0 < m_queue_map.size());
}
